package com.share.device.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.device.domain.Cabinet;
import com.share.device.domain.Station;
import com.share.device.domain.StationLocation;
import com.share.device.mapper.StationMapper;
import com.share.device.repository.StationLocationRepository;
import com.share.device.service.ICabinetService;
import com.share.device.service.IRegionService;
import com.share.device.service.IStationService;
import lombok.RequiredArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class StationServiceImpl extends ServiceImpl<StationMapper, Station> implements IStationService {

    private final ICabinetService cabinetService;

    private final IRegionService regionService;

    private final StationLocationRepository stationLocationRepository;


    /**
     * 查询站点列表，并关联填充柜机编号信息
     *
     * @param station 查询条件对象，包含站点名称、区域编码等筛选条件
     * @return 符合条件的站点列表，每个站点对象包含关联的柜机编号信息
     */
    @Override
    public List<Station> selectStationList(Station station) {
        // 根据查询条件获取站点列表
        List<Station> list = getStations(station);

        // 提取所有站点关联的柜机ID
        List<Long> cabinetIdList = list.stream().map(Station::getCabinetId).collect(Collectors.toList());

        // 构建柜机ID到柜机编号的映射关系
        Map<Long, String> cabinetIdToCabinetNoMap = new HashMap<>();

        // 批量查询柜机信息并构建映射
        if (!CollectionUtils.isEmpty(cabinetIdList)) {
            List<Cabinet> cabinetList = cabinetService.list(new LambdaQueryWrapper<Cabinet>().in(Cabinet::getId, cabinetIdList));

            // 将柜机ID和柜机编号映射存入Map
            cabinetIdToCabinetNoMap = cabinetList.stream().collect(Collectors.toMap(Cabinet::getId, Cabinet::getCabinetNo));
        }

        // 为每个站点填充柜机编号信息
        for (Station item : list) {
            item.setCabinetNo(cabinetIdToCabinetNoMap.get(item.getCabinetId()));
        }

        return list;
    }

    /**
     * 新增站点
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveStation(Station station) {
        // 省code
        String provinceName = regionService.getNameByCode(station.getProvinceCode());
        // 市code
        String cityName = regionService.getNameByCode(station.getCityCode());
        // 区code
        String districtName = regionService.getNameByCode(station.getDistrictCode());

        // 完整地址
        station.setFullAddress(provinceName + cityName + districtName + station.getAddress());

        this.save(station);

        // 同步站点位置信息到MongoDB
        StationLocation stationLocation = new StationLocation();

        stationLocation.setId(ObjectId.get().toString());
        stationLocation.setStationId(station.getId());
        stationLocation.setLocation(new GeoJsonPoint(station.getLongitude().doubleValue(), station.getLatitude().doubleValue()));
        stationLocation.setCreateTime(new Date());

        stationLocationRepository.save(stationLocation);

        return 1;
    }

    /**
     * 修改站点
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateStation(Station station) {
        // 省code
        String provinceName = regionService.getNameByCode(station.getProvinceCode());
        // 市code
        String cityName = regionService.getNameByCode(station.getCityCode());
        // 区code
        String districtName = regionService.getNameByCode(station.getDistrictCode());

        // 完整地址
        station.setFullAddress(provinceName + cityName + districtName + station.getAddress());

        this.updateById(station);

        // 同步站点位置信息到MongoDB
        StationLocation stationLocation = stationLocationRepository.getByStationId(station.getId());
        stationLocation.setLocation(new GeoJsonPoint(station.getLongitude().doubleValue(), station.getLatitude().doubleValue()));
        stationLocationRepository.save(stationLocation);

        return 1;
    }

    /**
     * 站点设置关联数据
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int setData(Station station) {
        this.updateById(station);

        // 更正柜机使用状态
        Cabinet cabinet = cabinetService.getById(station.getCabinetId());

        cabinet.setStatus("1");
        cabinetService.updateById(cabinet);

        return 1;
    }

    /**
     * 更新初始化数据
     */
    @Override
    public void updateData() {
        List<Station> stationList = this.list();

        for (Station station : stationList) {
            StationLocation stationLocation = stationLocationRepository.getByStationId(station.getId());

            if (stationLocation == null) {
                stationLocation = new StationLocation();

                stationLocation.setId(ObjectId.get().toString());
                stationLocation.setStationId(station.getId());
                stationLocation.setLocation(new GeoJsonPoint(station.getLongitude().doubleValue(), station.getLatitude().doubleValue()));
                stationLocation.setCreateTime(new Date());

                stationLocationRepository.save(stationLocation);
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeByIds(Collection<?> list) {
        for (Object id : list) {
            stationLocationRepository.deleteByStationId(Long.parseLong(id.toString()));
        }

        return super.removeByIds(list);
    }

    /**
     * 根据查询条件构建站点查询，并返回符合条件的站点列表
     *
     * @param station 包含查询条件的站点对象
     * @return 符合条件的站点列表
     */
    private List<Station> getStations(Station station) {
        // 提取查询条件参数
        String name = station.getName();            // 站点名称
        String provinceCode = station.getProvinceCode();  // 省编码
        String cityCode = station.getCityCode();    // 市编码
        String districtCode = station.getDistrictCode();  // 区编码
        String address = station.getAddress();      // 详细地址
        String headName = station.getHeadName();    // 站点负责人名称
        String headPhone = station.getHeadPhone();  // 站点负责人电话

        // 构建查询条件包装器
        LambdaQueryWrapper<Station> wrapper = new LambdaQueryWrapper<>();

        // 添加模糊查询条件：站点名称
        if (StrUtil.isNotEmpty(name)) {
            wrapper.like(Station::getName, name);
        }

        // 添加精确查询条件：省编码
        if (StrUtil.isNotEmpty(provinceCode)) {
            wrapper.eq(Station::getProvinceCode, provinceCode);
        }

        // 添加精确查询条件：市编码
        if (StrUtil.isNotEmpty(cityCode)) {
            wrapper.eq(Station::getCityCode, cityCode);
        }

        // 添加精确查询条件：区编码
        if (StrUtil.isNotEmpty(districtCode)) {
            wrapper.eq(Station::getDistrictCode, districtCode);
        }

        // 添加精确查询条件：详细地址
        if (StrUtil.isNotEmpty(address)) {
            wrapper.eq(Station::getAddress, address);
        }

        // 添加模糊查询条件：负责人名称
        if (StrUtil.isNotEmpty(headName)) {
            wrapper.like(Station::getHeadName, headName);
        }

        // 添加精确查询条件：负责人电话
        if (StrUtil.isNotEmpty(headPhone)) {
            wrapper.eq(Station::getHeadPhone, headPhone);
        }

        // 添加数据过滤条件：只查询未删除的站点
        wrapper.eq(Station::getDelFlag, "0");

        // 执行查询并返回结果
        return list(wrapper);
    }
}
